package org.luxor.commons.workflow.service.impl;

import org.activiti.bpmn.model.BpmnModel;
import org.activiti.engine.ActivitiException;
import org.activiti.engine.ActivitiObjectNotFoundException;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.DeploymentBuilder;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.image.impl.DefaultProcessDiagramGenerator;
import org.apache.commons.lang.StringUtils;
import org.luxor.commons.workflow.config.properties.WorkflowProperties;
import org.luxor.commons.workflow.entity.DeployProcess;
import org.luxor.commons.workflow.entity.ProcessDefinitionQuery;
import org.luxor.commons.workflow.service.IRepositoryCoreService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.io.InputStream;
import java.util.Collections;
import java.util.List;

/**
 * 流程定义
 *
 * @author Mr.yan  @date 2021/10/16
 */
@Service
public class RepositoryCoreServiceImpl implements IRepositoryCoreService {

    private static final Logger log = LoggerFactory.getLogger(RepositoryCoreServiceImpl.class);

    @Resource
    private RepositoryService repositoryService;
    @Resource
    private WorkflowProperties workflowProperties;

    /**
     * 部署
     */
    @Override
    public Deployment deploy(DeployProcess deployProcess, String resourceName, InputStream inputStream) {
        DeploymentBuilder deploymentBuilder = repositoryService.createDeployment()
                .tenantId(deployProcess.getTenantId())
                .category(deployProcess.getCategory())
                .name(deployProcess.getName())
                .addInputStream(resourceName, inputStream)
                .enableDuplicateFiltering();
        return deploymentBuilder.deploy();
    }

    /**
     * 卸载
     */
    @Override
    public void uninstall(String deploymentId) {
        repositoryService.deleteDeployment(deploymentId, true);
    }

    /**
     * 可发起流程列表
     */
    @Override
    public List<ProcessDefinition> listLastVer(ProcessDefinitionQuery query) {
        org.activiti.engine.repository.ProcessDefinitionQuery processDefinitionQuery = repositoryService.createProcessDefinitionQuery()
                .orderByDeploymentId().asc()
                .orderByProcessDefinitionVersion().desc()
                .active()
                .latestVersion();
        if (StringUtils.isNotBlank(query.getTenantId())) {
            processDefinitionQuery.processDefinitionTenantId(query.getTenantId());
        }
        if (StringUtils.isNotBlank(query.getCategory())) {
            processDefinitionQuery.processDefinitionCategory(query.getCategory());
        }
        if (StringUtils.isNotBlank(query.getName())) {
            processDefinitionQuery.processDefinitionNameLike("%" + query.getName() + "%");
        }
        if (StringUtils.isNotBlank(query.getKey())) {
            processDefinitionQuery.processDefinitionKeyLike("%" + query.getKey() + "%");
        }
        if (!CollectionUtils.isEmpty(query.getDeploymentIds())) {
            processDefinitionQuery.deploymentIds(query.getDeploymentIds());
        }
        return processDefinitionQuery.list();
    }

    /**
     * 历史流程列表
     */
    @Override
    public List<ProcessDefinition> listHistoryVer(String processDefinitionKey) {
        return repositoryService.createProcessDefinitionQuery()
                .processDefinitionKey(processDefinitionKey)
                .orderByProcessDefinitionVersion().desc()
                .list();
    }

    /**
     * 获取预览图
     */
    @Override
    public InputStream getImage(String processDefinitionId) {
        BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinitionId);
        if (bpmnModel == null) {
            throw new ActivitiObjectNotFoundException("Cannot find BpmnModel with processDefinitionId "
                    + processDefinitionId, BpmnModel.class);
        }
        String activityFontName = workflowProperties.getFontName();
        String labelFontName = workflowProperties.getFontName();
        String annotationFontName = workflowProperties.getFontName();
        List<String> highLightedActivities = Collections.emptyList();
        List<String> highLightedFlows = Collections.emptyList();

        return new DefaultProcessDiagramGenerator().generateDiagram(bpmnModel
                , highLightedActivities, highLightedFlows
                , activityFontName, labelFontName, annotationFontName);
    }

    /**
     * 导出
     */
    @Override
    public InputStream export(String processDefinitionId) {
        return repositoryService.getProcessModel(processDefinitionId);
    }


    /**
     * 查看
     */
    @Override
    public ProcessDefinition getByDeploymentId(String deploymentId) {
        org.activiti.engine.repository.ProcessDefinitionQuery processDefinitionQuery = repositoryService.createProcessDefinitionQuery()
                .deploymentId(deploymentId);
        return processDefinitionQuery.singleResult();
    }

    /**
     * 查看
     */
    @Override
    public ProcessDefinition get(String processDefinitionId) {
        org.activiti.engine.repository.ProcessDefinitionQuery processDefinitionQuery = repositoryService.createProcessDefinitionQuery()
                .processDefinitionId(processDefinitionId)
                .latestVersion();
        return processDefinitionQuery.singleResult();
    }

    /**
     * 激活
     */
    @Override
    public void activate(String processDefinitionId) {
        try {
            repositoryService.activateProcessDefinitionById(processDefinitionId);
        } catch (ActivitiException ae) {
            log.warn(ae.getMessage());
        }
    }

    /**
     * 挂起
     */
    @Override
    public void suspend(String processDefinitionId) {
        try {
            repositoryService.suspendProcessDefinitionById(processDefinitionId);
        } catch (ActivitiException ae) {
            log.warn(ae.getMessage());
        }
    }

}
